﻿using GameFramework;
using GameHelper.Generated;
using System;
using System.Collections.Generic;
using TowerDefence_Zombie.Data;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityGameFramework.Runtime;

namespace TowerDefence_Zombie
{
    public enum TowerInputType
    {
        None, UI, Scene
    }

    public partial class LevelControl : IReference
    {
        private bool _isCanOperate = false;

        private TowerInputType towerInputType;
        private int previewPlacementId;
        private int previewTowerGridId;
        private TowerData previewTowerData;
        private EntityTowerPreview previewTowerEntityLogic;

        //——TempFrame
        private Vector3 inputPosition;

        private UILevelMainInfoForm uIFightInfoForm;

        private bool _isCanOperaScene = true;

        public bool TryProcTowerBeginDrag(TowerData towerData, int level, TowerInputType inputType, int gridId = 0, int placementId = 0)
        {
            if (IsCanOperationTowerDrag() == false
                || CheckPreviewTowerState(towerData.Id) == false)
            {
                return false;
            }

            StableCameraController.Instance.IsCanDrag = false;

            towerInputType = inputType;

            if (inputType == TowerInputType.Scene)
            {
                previewPlacementId = placementId;
            }
            else previewTowerGridId = gridId;
            previewTowerData = towerData;

            uIFightInfoForm.RefreshPreviewUI(towerData.Id, level);
            if (TryGetPreviewTower(towerData.Id, out previewTowerEntityLogic))
            {
                var towerLevelData = towerData.GetTowerLevelData(level);
                var towerStar = dataPlayer.GetTowerStar(towerData.Id);
                var towerStarData = towerData.GetStarData(towerStar);
                previewTowerEntityLogic.RadiusVisualiser.RefreshRadius(towerLevelData.Range + towerStarData.RangeAddition);
            }
            TryRefreshInputInfo();
            return true;
        }

        public void ProcessInputOperate(bool isCanOperaSceneTower)
        {
            _isCanOperaScene = isCanOperaSceneTower;

            if (_isCanOperate == false)
            {
                var fightUI = (UILevelMainInfoForm)GameEntry.UI.GetUIForm(EnumUIForm.UILevelMainInfoForm);
                if (fightUI != null)
                {
                    uIFightInfoForm = fightUI;
                    _isCanOperate = true;
                }
                else return;
            }

            if (towerInputType != TowerInputType.None)
            {
                if (TryRefreshInputInfo())
                {
                    OnTowerDraging();
                }
                else OnTowerEndDrag();
            }
            else
            {
                if (_isCanOperaScene
                    && TrtTriggerInput()
                    && CheckPointerUI(inputPosition) == false
                    && TriggerPlacementArea(inputPosition, out var area, out var fitState, out _)
                    && fitState == TowerFitStatus.Overlaps
                    && dicPlacementTowerInfo.TryGetValue(area.AreaId, out var towerInfo)
                    && dataPlacement.GetPlacementAreaData(area.AreaId, out var areaData))
                {
                    var towerData = dataTower.GetTowerData(areaData.TowerId);
                    var towerLevel = areaData.TowerLevel;
                    if (TryProcTowerBeginDrag(towerData, towerLevel, TowerInputType.Scene, 0, area.AreaId))
                    {
                        SetTowerVisible(towerInfo.Tower.SerialId, false);
                    }
                }
            }
        }

        private void OnTowerDraging()
        {
            Vector3 dragPosition = inputPosition;
            if (uIFightInfoForm.DragSynthesisItemUI(dragPosition, !_isCanOperaScene))
            {
                if (previewTowerEntityLogic.Visible)
                {
                    previewTowerEntityLogic.Visible = false;
                }
            }
            else
            {
                if (previewTowerEntityLogic.Visible == false)
                {
                    previewTowerEntityLogic.Visible = true;
                }
                if (TriggerPlacementArea(dragPosition, out var area, out var fitState, out var gridPos)
                    && (fitState == TowerFitStatus.Fits || fitState == TowerFitStatus.Overlaps))
                {
                    previewTowerEntityLogic.transform.SetPositionAndRotation
                        (area.GridToWorld(gridPos, previewTowerData.Dimensions), area.transform.rotation);
                }
                else
                {
                    Vector3 mousePos = new(dragPosition.x, dragPosition.y, 300);
                    previewTowerEntityLogic.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
                }
            }
        }

        private void OnTowerEndDrag()
        {
            if (towerInputType == TowerInputType.None) return;

            StableCameraController.Instance.IsCanDrag = true;

            bool isOperationSuccess = false;
            if (uIFightInfoForm.CheckDragIsOverlyUI(inputPosition))
            {
                isOperationSuccess = TryTriggerUISynthesis(inputPosition);
            }
            else if (TriggerPlacementArea(inputPosition, out var area, out var fitState, out _)
                && fitState != TowerFitStatus.Lock
                && fitState != TowerFitStatus.OutOfBounds
                && dataPlacement.GetPlacementAreaData(area.AreaId, out var tarPlaceGridData))
            {
                isOperationSuccess = TrySynthesisToPlaceTower(tarPlaceGridData);
            }

            if (isOperationSuccess == false)
            {
                if (towerInputType == TowerInputType.Scene
                    && dicPlacementTowerInfo.TryGetValue(previewPlacementId, out var towerInfo))
                {
                    SetTowerVisible(towerInfo.Tower.SerialId, true);
                }
            }
            HideAllPreviewTower();
            previewTowerEntityLogic = null;
            uIFightInfoForm.StopDragSynthesisItemUI(isOperationSuccess);
            towerInputType = TowerInputType.None;
        }

        #region 将炮塔往UI上进行拖拽

        private bool CheckPointerUI(Vector3 curInputPos)
        {
            PointerEventData eventData = new(EventSystem.current)
            {
                position = curInputPos
            };

            List<RaycastResult> results = new();
            EventSystem.current.RaycastAll(eventData, results);
            return results.Count > 0;
        }

        private bool TryTriggerUISynthesis(Vector3 curInputPos)
        {
            if (CheckPointerUI(curInputPos))
            {
                List<RaycastResult> eventResult = new();
                PointerEventData pointEvent = new(EventSystem.current) { position = curInputPos };
                EventSystem.current.RaycastAll(pointEvent, eventResult);
                for (int i = 0; i < eventResult.Count; i++)
                {
                    var targetPointerObj = eventResult[i].gameObject;
                    if (targetPointerObj.CompareTag(TagDefines.UISynthesisItem)
                        && targetPointerObj.TryGetComponent(out ItemTowerGrid uiTowerGrid)
                        && dataSynthesis.GetSynthesisGridData(uiTowerGrid.GetGridRealId(), out var tarUIGridData))
                    {
                        return TrySynthesisToUITowerGrid(tarUIGridData);
                    }
                    else if (targetPointerObj.CompareTag(TagDefines.UISynthesisRecycle))
                    {
                        if (owner.GuideControl.IsDisableRecycle == false)
                        {
                            TriggerRecycleBin();
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        private bool TrySynthesisToUITowerGrid(BaseTowerGridData targetUITowerGridData)
        {
            if (towerInputType == TowerInputType.Scene) //从放置位上往UI上进行拖拽
            {
                if (dataPlacement.GetPlacementAreaData(previewPlacementId, out var origPlaceTowerGridData))
                {
                    return dataSynthesis.TrySynthesisGrid(origPlaceTowerGridData, targetUITowerGridData);
                }
            }
            else //UI装备栏之间互相拖拽
            {
                if (previewTowerGridId != targetUITowerGridData.Id
                    && dataSynthesis.GetSynthesisGridData(previewTowerGridId, out var origUITowerGridData))
                {
                    return dataSynthesis.TrySynthesisGrid(origUITowerGridData, targetUITowerGridData);
                }
            }
            return false;
        }

        private void TriggerRecycleBin()
        {
            int towerLevel = 1;
            int towerId = -1;
            if (towerInputType == TowerInputType.Scene)
            {
                towerId = previewPlacementId;
                if (dataPlacement.GetPlacementAreaData(previewPlacementId, out var placemenData))
                {
                    towerLevel = placemenData.TowerLevel;
                }
                dataPlacement.ChangePlacementAreaTower(previewPlacementId, 0, 0);
                Log.Info("删除放置位上的炮塔");
            }
            else
            {
                towerId = previewTowerGridId;
                if (dataSynthesis.GetSynthesisGridData(previewTowerGridId, out var gridData))
                {
                    towerLevel = gridData.TowerLevel;
                }
                dataSynthesis.ChangeSynthesisGridTower(previewTowerGridId, 0, 0);
                Log.Info("删除装备栏上的炮塔");
            }

            if (dataTower.GetTowerBuildData(towerLevel + 1, out var builderData))
            {
                //删除炮塔，需要反一些金币
                dataPlayer.AddCurrency(builderData.BuildItems, builderData.RecycleCurrencyNum, CurrencyEvent.RecycleTower);
            }

            int curBattleLevel = GameEntry.Data.GetData<DataPlayer>().GetCurBattleLevel();
            Dictionary<string, string> dic = new()
            {
                { "ID", towerId.ToString() },
                { "level",(towerLevel).ToString() },
                { "G",curBattleLevel.ToString() },
            };
            UPTrace.UPTraceApi.traceDictionary("T0_delete", dic);
        }

        #endregion

        #region 将炮塔往放置位上进行拖拽

        private bool TriggerPlacementArea(Vector3 curInputPos
            , out IPlacementArea area
            , out TowerFitStatus fitState
            , out IntVector2 gridPos)
        {
            Ray ray = Camera.main.ScreenPointToRay(curInputPos);
            if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, 1 << LayerDefines.PlacementLayerValue)
                && hit.collider.TryGetComponent(out area))
            {
                gridPos = area.WorldToGrid(hit.point, new IntVector2(2, 2));
                fitState = area.Fits(gridPos, new IntVector2(2, 2));
                return true;
            }
            area = null;
            gridPos = IntVector2.zero;
            fitState = TowerFitStatus.OutOfBounds;
            return false;
        }

        private bool TrySynthesisToPlaceTower(BaseTowerGridData tarPlaceGridData)
        {
            if (towerInputType == TowerInputType.Scene) //放置位之间的互相拖拽
            {
                if (previewPlacementId != tarPlaceGridData.Id
                    && dataPlacement.GetPlacementAreaData(previewPlacementId, out var origPlaceTowerGridData))
                {
                    return dataPlacement.TrySynthesisPlaceGrid(origPlaceTowerGridData, tarPlaceGridData);
                }
            }
            else //从UI上往放置位上进行拖拽
            {
                if (dataSynthesis.GetSynthesisGridData(previewTowerGridId, out var origUITowerGridData))
                {
                    return dataPlacement.TrySynthesisPlaceGrid(origUITowerGridData, tarPlaceGridData);
                }
            }
            return false;
        }

        #endregion

        private bool IsCanOperationTowerDrag()
        {
            return _isCanOperate && towerInputType == TowerInputType.None;
        }

        private bool TrtTriggerInput()
        {
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
            if (Input.GetMouseButtonDown(0))
            {
                inputPosition = Input.mousePosition;
                return CheckPointerUI(inputPosition) == false;
            }
#elif UNITY_ANDROID || UNITY_IOS
            if (Input.touchCount == 1
                && Input.GetTouch(0).phase == TouchPhase.Began)
            {
                inputPosition = Input.GetTouch(0).position;
                return CheckPointerUI(inputPosition) == false;
            }
#endif
            return false;
        }

        private bool TryRefreshInputInfo()
        {
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
            if (Input.GetMouseButton(0))
            {
                inputPosition = Input.mousePosition;
                return true;
            }
#elif UNITY_ANDROID || UNITY_IOS
            if (Input.touchCount == 1
                && Input.GetTouch(0).phase != TouchPhase.Ended
                && Input.GetTouch(0).phase != TouchPhase.Canceled)
            {
                inputPosition = Input.GetTouch(0).position;
                return true;
            }
#endif
            return false;
        }
    }
}
